/*   Copyright  2009
 *  @Author
 *  Richard Changde Yin            e-mail yinchangde@hotmail.com
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; version 2 of the License.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */
/**
 *  @filename: global.h
 */
/* This is the include file that should be included 'first' in every C file. */

#ifndef __DB_GLOBAL_H__
#define __DB_GLOBAL_H__

#if defined(i386) && !defined(__i386__)
#define __i386__
#endif

#include <config.h>

#if defined(__cplusplus)

typedef int  (*qsort_cmp2)(void*, const void *,const void *);


#define my_errno (errno)



# include CSTDINT_H
# include CINTTYPES_H
# include <cstdio>
# include <cstdlib>
# include <cstddef>
# include <cassert>
# include <cerrno>
# include <sstream>
# if defined(HAVE_MEMORY)
#  include <memory>
# endif
# if defined(HAVE_TR1_MEMORY)
#  include <tr1/memory>
# endif
# if defined(HAVE_BOOST_SHARED_PTR_HPP)
#  include <boost/shared_ptr.hpp>
# endif
#else
# include <stdint.h>
# include <inttypes.h>
# include <stdio.h>
# include <stdlib.h>
# include <stddef.h>
# include <errno.h>        /* Recommended by debian */




/*
  A lot of our programs uses asserts, so better to always include it
*/
# include <assert.h>
# include <stdbool.h>

#endif // __cplusplus

#include <math.h>

#ifndef EOVERFLOW
#define EOVERFLOW 84
#endif
# include <definitions.h>   // for myf

#if TIME_WITH_SYS_TIME
# include <sys/time.h>
# include <time.h>
#else
# if HAVE_SYS_TIME_H
#  include <sys/time.h>
# else
#  include <time.h>
# endif
#endif
#ifndef HAVE_DECL_TIMEGM
#include <gnulib/time.h>
# if defined(__cplusplus)
extern "C"
# endif
time_t timegm (struct tm *__tm);
#endif /* HAVE_DECL_TIMEGM */


/* root_alloc flags */
#define MY_KEEP_PREALLOC        1
#define MY_MARK_BLOCKS_FREE     2  /* move used to free list and reuse them */


#if defined(__cplusplus)
# if !defined(SHARED_PTR_NAMESPACE)
#  error SHARED_PTR_NAMESPACE not defined, configure error!
# endif
# if defined(SHARED_PTR_NAMESPACE)
//We aren't using this yet - don't actually put in code yet.
//using SHARED_PTR_NAMESPACE::shared_ptr;
# endif
#endif /* defined(SHARED_PTR_NAMESPACE) */

/*
  Temporary solution to solve bug#7156. Include "sys/types.h" before
  the thread headers, else the function madvise() will not be defined
*/
#if defined(HAVE_SYS_TYPES_H) && ( defined(sun) || defined(__sun) )
#include <sys/types.h>
#endif


#include <pthread.h>    /* AIX must have this included first */

#define _REENTRANT  1   /* Threads requires reentrant code   */

#ifdef HAVE_LIMITS_H
#include <limits.h>
#endif

#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#ifdef HAVE_FCNTL_H
#include <fcntl.h>
#endif

#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif


#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
#endif

/* Declared in int2str() */
extern char _dig_vec_upper[];
extern char _dig_vec_lower[];

#ifdef __cplusplus
template <class T> void set_if_bigger(T &a, const T &b)
{
  if (a < b)
    a=b;
}

template <class T> void set_if_smaller(T &a, const T &b)
{
  if (a > b)
    a=b;
}
#else
#ifdef __GNUC__
#define set_if_bigger(a,b) do {                 \
  const typeof(a) _a = (a);                     \
  const typeof(b) _b = (b);                     \
  (void) (&_a == &_b);                          \
  if ((a) < (b)) (a)=(b);                       \
  } while(0)
#define set_if_smaller(a,b) do {                \
  const typeof(a) _a = (a);                     \
  const typeof(b) _b = (b);                     \
  (void) (&_a == &_b);                          \
  if ((a) > (b)) (a)=(b);                       \
  } while(0)

#else
#define set_if_bigger(a,b)  do { if ((a) < (b)) (a)=(b); } while(0)
#define set_if_smaller(a,b) do { if ((a) > (b)) (a)=(b); } while(0)
#endif
#endif

#define array_elements(A) ((size_t) (sizeof(A)/sizeof(A[0])))

/* Some types that is different between systems */

typedef int  File;    /* File descriptor */

#ifdef HAVE_SYS_SOCKET_H
#include <sys/socket.h>
#endif

#define DOT         "."
#define DOT_CHAR    '.'
#ifndef FN_LIBCHAR
#define FN_LIBCHAR  '/'
#define FN_ROOTDIR  "/"
#endif
#define CLPSAR_NFILE  64  /* This is only used to save filenames */
#ifndef OS_FILE_LIMIT
#define OS_FILE_LIMIT    65535
#endif

/*
  How much overhead does malloc have. The code often allocates
  something like 1024-MALLOC_OVERHEAD bytes
*/
#define MALLOC_OVERHEAD 8

/* get memory in huncs */
#define ONCE_ALLOC_INIT    (uint32_t) (4096-MALLOC_OVERHEAD)
/* Typical record cash */
#define RECORD_CACHE_SIZE  (uint32_t) (64*1024-MALLOC_OVERHEAD)
/* Typical key cash */
#define KEY_CACHE_SIZE     (uint32_t) (8*1024*1024-MALLOC_OVERHEAD)
/* Default size of a key cache block  */
#define KEY_CACHE_BLOCK_SIZE  (uint32_t) 1024


/* Some things that this system doesn't have */

/* Some defines of functions for portability */

#undef remove
#ifndef uint64_t2double
#define uint64_t2double(A)      ((double) (uint64_t) (A))
#define clpsar_off_t2double(A)  ((double) (clpsar_off_t) (A))
#endif

#ifndef offsetof
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
#endif
#define ulong_to_double(X) ((double) (ulong) (X))

#ifndef STACK_DIRECTION
#error "please add -DSTACK_DIRECTION=1 or -1 to your CPPFLAGS"
#endif

#ifdef HAVE_FLOAT_H
#include <float.h>
#else
#if !defined(FLT_MIN)
#define FLT_MIN         ((float)1.40129846432481707e-45)
#endif
#if !defined(FLT_MAX)
#define FLT_MAX         ((float)3.40282346638528860e+38)
#endif
#endif

/* From limits.h instead */
#ifndef DBL_MIN
#define DBL_MIN    4.94065645841246544e-324
#endif
#ifndef DBL_MAX
#define DBL_MAX    1.79769313486231470e+308
#endif
#ifndef SIZE_T_MAX
#define SIZE_T_MAX ~((size_t) 0)
#endif


/* Define missing math constants. */
#ifndef M_PI
#define M_PI 3.14159265358979323846
#endif
#ifndef M_E
#define M_E 2.7182818284590452354
#endif
#ifndef M_LN2
#define M_LN2 0.69314718055994530942
#endif

/*
  Max size that must be added to a so that we know Size to make
  addressable object.
*/
typedef ptrdiff_t my_ptrdiff_t;

#define COLLAPSAR_ALIGN(A,L)  (((A) + (L) - 1) & ~((L) - 1))
#define ALIGN_SIZE(A)         COLLAPSAR_ALIGN((A),sizeof(double))
/* Size to make addressable obj. */
#define ALIGN_PTR(A, t)      ((t*) COLLAPSAR_ALIGN((A),sizeof(t)))
/* Offset of field f in structure t */
#define OFFSET(t, f)  ((size_t)(char *)&((t *)0)->f)
#define ADD_TO_PTR(ptr,size,type) (type) ((unsigned char*) (ptr)+size)
#define PTR_BYTE_DIFF(A,B) (my_ptrdiff_t)((unsigned char*) (A)-(unsigned char*) (B))

#define COLLAPSAR_DIV_UP(A, B) (((A) + (B) - 1) / (B))
#define COLLAPSAR_ALIGNED_BYTE_ARRAY(N, S, T) T N[COLLAPSAR_DIV_UP(S, sizeof(T))]

/* Typdefs for easier portability */

#if !defined(HAVE_ULONG) && !defined(__USE_MISC)
typedef unsigned long ulong;      /* Short for unsigned long */
#endif

typedef uint64_t clpsar_off_t;
typedef uint64_t db_off_t    ;

#if defined(SIZEOF_OFF_T)
# if (SIZEOF_OFF_T == 8)
#  define OFF_T_MAX (INT64_MAX)
# else
#  define OFF_T_MAX (INT32_MAX)
# endif
#endif

#define COLLAPSAR_FILEPOS_ERROR  -1

/* Defines for time function */
#define SCALE_SEC  100
#define SCALE_USEC  10000
#define COLLAPSAR_HOW_OFTEN_TO_ALARM  2  /* How often we want info on screen */
#define COLLAPSAR_HOW_OFTEN_TO_WRITE  1000  /* How often we want info on screen */


#if defined(HAVE_CHARSET_utf8mb3) || defined(HAVE_CHARSET_utf8mb4)
#define COLLAPSAR_UNIVERSAL_CLIENT_CHARSET "utf8"
#else
#define COLLAPSAR_UNIVERSAL_CLIENT_CHARSET COLLAPSAR_DEFAULT_CHARSET_NAME
#endif

#include <dlfcn.h>

/* FreeBSD 2.2.2 does not define RTLD_NOW) */
#ifndef RTLD_NOW
#define RTLD_NOW 1
#endif

#define cmax(a, b)       ((a) > (b) ? (a) : (b))
#define cmin(a, b)       ((a) < (b) ? (a) : (b))

#define COLLAPSAR_SERVER

/* Length of decimal number represented by INT32. */
#define COLLAPSAR_INT32_NUM_DECIMAL_DIGITS 11

/* Length of decimal number represented by INT64. */
#define COLLAPSAR_INT64_NUM_DECIMAL_DIGITS 21

#define PROTOCOL_VERSION 10
/*
  Io buffer size; Must be a power of 2 and
  a multiple of 512. May be
  smaller what the disk page size. This influences the speed of the
  isam btree library. eg to big to slow.
*/
#define IO_SIZE 4096
/* Max file name len */
#define FN_LEN    256
/* Max length of extension (part of FN_LEN) */
#define FN_EXTLEN 20
/* Max length of full path-name */
#define FN_REFLEN 512
/* File extension character */
#define FN_EXTCHAR '.'
/* ~ is used as abbrev for home dir */
#define FN_HOMELIB '~'
/* ./ is used as abbrev for current dir */
#define FN_CURLIB '.'
/* Parent directory; Must be a string */
#define FN_PARENTDIR ".."

/* Quote argument (before cpp) */
#ifndef QUOTE_ARG
# define QUOTE_ARG(x) #x
#endif
/* Quote argument, (after cpp) */
#ifndef STRINGIFY_ARG
# define STRINGIFY_ARG(x) QUOTE_ARG(x)
#endif


	/* General bitmaps   */
#define MY_FFNF     1   /* Fatal if file not found */
#define MY_FNABP    2    /* Fatal if not all bytes read/writen */
#define MY_NABP     4    /* Error if not all bytes read/writen */
#define MY_FAE      8     /* Fatal if any error */
#define MY_WME     16    /* Write message on error */
#define MY_WAIT_IF_FULL 32	/* Wait and try again if disk full error */
#define MY_IGNORE_BADFD 32      /* my_sync: ignore 'bad descriptor' errors */
#define MY_SYNC_DIR     1024    /* db_create_file/delete/rename: sync directory */
#define MY_FULL_IO     512      /* For my_read - loop intil I/O is complete */
#define MY_DONT_CHECK_FILESIZE 128 /* Option to init_io_cache() */
#define MY_LINK_WARNING 32      /* my_redel() gives warning if links */
#define MY_COPYTIME     64      /* my_redel() copys time */
#define MY_DELETE_OLD   256     /* my_create_with_symlink() */
#define MY_RESOLVE_LINK 128     /* db_realpath(); Only resolve links */
#define MY_HOLD_ORIGINAL_MODES 128  /* db_copy_file() holds to file modes */
#define MY_REDEL_MAKE_BACKUP 256
#define MY_DONT_WAIT 64  /* my_lock() don't wait if can't lock */
#define MY_ZEROFILL  32  /* util_multi_malloc(), fill array with zero */
#define MY_DONT_OVERWRITE_FILE 1024	/* my_copy: Don't overwrite file */
#define MY_THREADSAFE 2048      /* my_seek(): lock fd mutex */



	/* Bits in last argument to fn_format */
#define MY_REPLACE_DIR        1  /* replace dir in name with 'dir' */
#define MY_REPLACE_EXT        2  /* replace extension with 'ext' */
#define MY_UNPACK_FILENAME    4  /* Unpack name (~ -> home) */
#define MY_PACK_FILENAME      8  /* Pack name (home -> ~) */
#define MY_RESOLVE_SYMLINKS   16 /* Resolve all symbolic links */
#define MY_RETURN_REAL_PATH   32 /* return full path for file */
#define MY_SAFE_PATH          64 /* Return NULL if too long path */
#define MY_RELATIVE_PATH     128 /* name is relative to 'dir' */
#define MY_APPEND_EXT       256     /* add 'ext' as additional extension*/


#define ME_HIGHBYTE 8   /* Shift for colours */
#define ME_NOCUR    1   /* Don't use curses message */
#define ME_OLDWIN   2   /* Use old window */
#define ME_BELL     4   /* Ring bell then printing message */
#define ME_HOLDTANG  8  /* Don't delete last keys */
#define ME_WAITTOT   16  /* Wait for errtime secs of for a action */
#define ME_WAITTANG  32  /* Wait for a user action  */
#define ME_NOREFRESH 64 /* Dont refresh screen */
#define ME_NOINPUT  128 /* Dont use the input libary */
#define ME_COLOUR1  ((1 << ME_HIGHBYTE))    /* Possibly error-colours */
#define ME_COLOUR2  ((2 << ME_HIGHBYTE))
#define ME_COLOUR3  ((3 << ME_HIGHBYTE))
#define ME_FATALERROR   1024    /* Fatal statement error */

/* Some constants */
#define MY_WAIT_FOR_USER_TO_FIX_PANIC  60 /* in seconds */
#define MY_WAIT_GIVE_USER_A_MESSAGE 10    /* Every 10 times of prev */

/*
 * The macros below are borrowed from include/linux/compiler.h in the
 * Linux kernel. Use them to indicate the likelyhood of the truthfulness
 * of a condition. This serves two purposes - newer versions of gcc will be
 * able to optimize for branch predication, which could yield siginficant
 * performance gains in frequently executed sections of the code, and the
 * other reason to use them is for documentation
 */
#if !defined(__GNUC__)
#define __builtin_expect(x, expected_value) (x)
#endif

#define likely(x)  __builtin_expect((x),1)
#define unlikely(x)  __builtin_expect((x),0)


/*
  Only Linux is known to need an explicit sync of the directory to make sure a
  file creation/deletion/renaming in(from,to) this directory durable.
*/
#ifdef TARGET_OS_LINUX
#define NEED_EXPLICIT_SYNC_DIR 1
#endif

/* We need to turn off _DTRACE_VERSION if we're not going to use dtrace */
#if !defined(HAVE_DTRACE)
# undef _DTRACE_VERSION
# define _DTRACE_VERSION 0
#endif


#define MAX_FILE_LEN             1024

#define IDENTIFIER_LENGTH        1024

#define ERROR_STRING_LENGTH      128

#define DEFAULT_VALUE_BUF_LENGTH  32

#define SYSTEMDB                "SYSTEMDB"
#define USERDB                  "userdb"

#define DBAUSER                 "root"
#define DBAPASS                 "manager"
#define LOCK_BUCKET_SIZE         2048

#define MAX_CHUNKS               20

#define PAGE_SIZE Conf::config.getPageSize()

#define MAX_MUTEX_PER_THREAD    5

#define MAX_THREADS_PER_PROCESS 1024

#define MAX_FILE_PATH_LEN 1024
/*The chunk name length*/
#define CHUNK_NAME_LEN      1280

#define BIT(x) (1 << (x))
#define SETBITS(x,y) ((x) |= (y))
#define CLEARBITS(x,y) ((x) &= (~(y)))
#define SETBIT(x,y) SETBITS((x), (BIT((y))))
#define CLEARBIT(x,y) CLEARBITS((x), (BIT((y))))
#define BITSET(x,y) ((x) & (BIT(y)))

enum ha_base_keytype {
  HA_KEYTYPE_END       =0,
  HA_KEYTYPE_TEXT      =1,           /* Key is sorted as letters */
  HA_KEYTYPE_BINARY    =2,           /* Key is sorted as unsigned chars */
  HA_KEYTYPE_SHORT_INT =3,
  HA_KEYTYPE_LONG_INT  =4,
  HA_KEYTYPE_FLOAT     =5,
  HA_KEYTYPE_DOUBLE    =6,
  HA_KEYTYPE_NUM       =7,            /* Not packed num with pre-space */
  HA_KEYTYPE_USHORT_INT=8,
  HA_KEYTYPE_ULONG_INT =9,
  HA_KEYTYPE_LONGLONG  =10,
  HA_KEYTYPE_ULONGLONG =11,
  HA_KEYTYPE_INT24     =12,
  HA_KEYTYPE_UINT24    =13,
  HA_KEYTYPE_INT8      =14,
  /* Varchar (0-255 bytes) with length packed with 1 byte */
  HA_KEYTYPE_VARTEXT1  =15,               /* Key is sorted as letters */
  HA_KEYTYPE_VARBINARY1=16,             /* Key is sorted as unsigned chars */
  /* Varchar (0-65535 bytes) with length packed with 2 bytes */
  HA_KEYTYPE_VARTEXT2  =17,     /* Key is sorted as letters */
  HA_KEYTYPE_VARBINARY2=18,     /* Key is sorted as unsigned chars */
  HA_KEYTYPE_BIT       =19
};

#include <m_ctype.h>

/* For number of records */
typedef uint64_t        ha_rows;
#define rows2double(A)  uint64_t2double(A)


/*
  config.h

*/
#define COLLAPSAR_PAGE_SIZE    8192
#define COLLAPSAR_SYS_DBKEY    19722
#define COLLAPSAR_USER_DBKEY   28555

#define get_key_length(length,key) \
{ if (*(unsigned char*) (key) != 255) \
    length= (uint) *(unsigned char*) ((key)++); \
  else \
  { length= mi_uint2korr((key)+1); (key)+=3; } \
}

#define get_key_length_rdonly(length,key) \
{ if (*(unsigned char*) (key) != 255) \
    length= ((uint) *(unsigned char*) ((key))); \
  else \
  { length= mi_uint2korr((key)+1); } \
}

#define get_key_pack_length(length,length_pack,key) \
{ if (*(unsigned char*) (key) != 255) \
  { length= (uint) *(unsigned char*) ((key)++); length_pack= 1; }\
  else \
  { length=mi_uint2korr((key)+1); (key)+= 3; length_pack= 3; } \
}

#define store_key_length_inc(key,length) \
{ if ((length) < 255) \
  { *(key)++= (length); } \
  else \
  { *(key)=255; mi_int2store((key)+1,(length)); (key)+=3; } \
}


#define mi_int1store(T,A) *((unsigned char*)(T))= (unsigned char) (A)

#define mi_int2store(T,A)   { uint32_t def_temp= (uint32_t) (A) ;\
                              ((unsigned char*) (T))[1]= (unsigned char) (def_temp);\
                              ((unsigned char*) (T))[0]= (unsigned char) (def_temp >> 8); }
#define mi_int3store(T,A)   { /*lint -save -e734 */\
                              uint32_t def_temp= (uint32_t) (A);\
                              ((unsigned char*) (T))[2]= (unsigned char) (def_temp);\
                              ((unsigned char*) (T))[1]= (unsigned char) (def_temp >> 8);\
                              ((unsigned char*) (T))[0]= (unsigned char) (def_temp >> 16);\
                              /*lint -restore */}
#define mi_int4store(T,A)   { uint32_t def_temp= (uint32_t) (A);\
                              ((unsigned char*) (T))[3]= (unsigned char) (def_temp);\
                              ((unsigned char*) (T))[2]= (unsigned char) (def_temp >> 8);\
                              ((unsigned char*) (T))[1]= (unsigned char) (def_temp >> 16);\
                              ((unsigned char*) (T))[0]= (unsigned char) (def_temp >> 24); }

#define MM_UNIQUE_HASH_LENGTH    4

#undef TERMINATE
#define TERMINATE(A,B) {}



#ifdef  __cplusplus
extern "C"  {
#endif

#define HA_MAX_POSSIBLE_KEY         255         /* For myisamchk */
/*
  The following defines can be increased if necessary.
  But beware the dependency of MI_MAX_POSSIBLE_KEY_BUFF and HA_MAX_KEY_LENGTH.
*/

#define HA_MAX_KEY_LENGTH           1332        /* Max length in bytes */
#define HA_MAX_KEY_SEG              16          /* Max segments for key */

#define HA_MAX_POSSIBLE_KEY_BUFF    (HA_MAX_KEY_LENGTH + 24+ 6+6)
#define HA_MAX_KEY_BUFF  (HA_MAX_KEY_LENGTH+HA_MAX_KEY_SEG*6+8+8)


#define T_EXTEND                512
#define T_CHECK_ONLY_CHANGED    32             /* QQ to be removed */
#define T_FAST                  (1L << 10)     /* QQ to be removed */
#define T_FORCE_CREATE          (1L << 11)     /* QQ to be removed */
#define T_FORCE_UNIQUENESS      (1L << 12)
#define T_INFO                  (1L << 13)
#define T_MEDIUM                (1L << 14)
#define T_QUICK                 (1L << 15)     /* QQ to be removed */

struct charset_info_st;
/* m_ctype.h*/
//typedef struct charset_info_st CHARSET_INFO ;

/*
charsets
*/
extern CHARSET_INFO compiled_charsets[];
#define TRASH(A,B) /* nothing */

typedef uint32_t ha_checksum;

enum file_type
{
	  UNOPEN = 0,
	  FILE_BY_OPEN,
	  FILE_BY_CREATE,
	  STREAM_BY_FOPEN,
	  STREAM_BY_FDOPEN,
	  FILE_BY_MKSTEMP,
	  FILE_BY_DUP
};

typedef struct st_my_file_info
{
  char *            name;
  enum file_type    type;
}ST_FILE_INFO;
extern bool my_disable_symlinks;
extern struct st_my_file_info *my_file_info;




#ifdef EXTRA_DEBUG
void    db_print_open_files(void);
#else
#define db_print_open_files()
#endif
extern char* home_dir ;
extern size_t dirname_part(char * to,const char *name, size_t *to_res_length);
extern size_t dirname_length(const char *name);
#define base_name(A) (A+dirname_length(A))
static inline bool test_if_hard_path(const char *dir_name)
{
  if (dir_name[0] == FN_HOMELIB && dir_name[1] == FN_LIBCHAR)
    return (home_dir != NULL && test_if_hard_path(home_dir));
  if (dir_name[0] == FN_LIBCHAR)
    return (true);
  return false;
} /* test_if_hard_path */

extern size_t unpack_dirname(char * to,const char *from);
extern size_t cleanup_dirname(char * to,const char *from);
extern size_t system_filename(char * to,const char *from);
extern size_t unpack_filename(char * to,const char *from);
extern char * intern_filename(char * to,const char *from);

extern char *convert_dirname(char *to, const char *from, const char *from_end);

extern int  db_sync(File fd, myf my_flags);
extern int  db_sync_dir(const char *dir_name, myf my_flags);
extern int  db_sync_dir_by_file(const char *file_name, myf my_flags);

extern int  db_symlink(const char *content, const char *linkname, myf in_Flags);
extern int  db_delete_file_with_symlink(const char *name, myf in_Flags) ;

extern int  db_copy_file(const char *from,const char *to,myf _Flags);

extern int  db_delete_file(const char *name,myf _Flags);

extern File db_open_file(const char *FileName,int Flags,myf _Flags);

extern File db_register_filename(File fd, const char *FileName,
                                 enum file_type type_of_file,
                                 uint32_t error_message_number,
	                                 myf _Flags);
extern File db_create_file(const char *FileName,int CreateFlags,
                                  int AccessFlags, myf _Flags);
extern int  db_close_file(File Filedes,myf MyFlags);

extern char* db_filename(File fd);

extern int  db_readlink(char *to, const char *filename, myf in_Flags);
extern int  db_realpath(char *to, const char *filename, myf in_Flags);

extern char * fn_ext(const char *name);
extern char * fn_same(char * toname,const char *name,int flag);
extern char * fn_format(char * to,const char *name,const char *dir,
                        const char *form, uint32_t flag);
extern size_t strlength(const char *str)                ;

extern size_t db_read (File Filedes,  unsigned char *Buffer,size_t Count,
                       myf in_Flags);
extern int    db_rename(const char *from,const char *to,myf in_Flags);

extern size_t db_write(File Filedes,const unsigned char *Buffer,size_t Count,
                       myf in_Flags);

extern char * db_load_path(char * to, const char *path,
                           const char *own_path_prefix) ;

extern const char *get_relative_path(const char *path , const char* prefix);
/**
 * array.cc
 */
typedef struct st_dynamic_array
{
  unsigned char *buffer;
  size_t elements,max_element;
  uint32_t alloc_increment;
  uint32_t size_of_element;
} DYNAMIC_ARRAY;

#define reset_dynamic(array) ((array)->elements= 0)

File create_temp_file(char *to, const char *dir, const char *pfx,
                      myf _Flags);

#define my_init_dynamic_array(A,B,C,D)    init_dynamic_array2(A,B,NULL,C,D)
#define macro_init_dynamic_array(A,B,C,D)    my_init_dynamic_array(A,B,C,D)
#define init_dynamic_array_ci(A,B,C,D) init_dynamic_array2(A,B,NULL,C,D)
#define my_init_dynamic_array2(A,B,C,D,E)    init_dynamic_array2(A,B,C,D,E)
#define my_init_dynamic_array2_ci(A,B,C,D,E) init_dynamic_array2(A,B,C,D,E)

extern bool init_dynamic_array2(DYNAMIC_ARRAY *array,uint32_t element_size,
                                   void *init_buffer, uint32_t init_alloc,
                                   uint32_t alloc_increment);

/* init_dynamic_array() function is deprecated */
extern bool init_dynamic_array(DYNAMIC_ARRAY *array,uint32_t element_size,
                                  uint32_t init_alloc,uint32_t alloc_increment);
extern bool insert_dynamic(DYNAMIC_ARRAY *array,unsigned char * element);
extern unsigned char *alloc_dynamic(DYNAMIC_ARRAY *array);
extern unsigned char *pop_dynamic(DYNAMIC_ARRAY*);
extern bool set_dynamic(DYNAMIC_ARRAY *array,unsigned char * element,uint32_t array_index);
extern bool allocate_dynamic(DYNAMIC_ARRAY *array, uint32_t max_elements);
extern void get_dynamic(DYNAMIC_ARRAY *array,unsigned char * element,uint32_t array_index);
extern void delete_dynamic(DYNAMIC_ARRAY *array);
extern void delete_dynamic_element(DYNAMIC_ARRAY *array, uint32_t array_index);
extern void freeze_size(DYNAMIC_ARRAY *array);
extern int  get_index_dynamic(DYNAMIC_ARRAY *array, unsigned char * element);
extern int wild_compare(const char *str,const char *wildstr,
                        bool str_is_pattern);

#define dynamic_element(array,array_index,type) ((type)((array)->buffer) +(array_index))
#define dynamic_array_ptr(array,array_index) ((array)->buffer+(array_index)*(array)->size_of_element)
/*  mf_qsort.cc*/
typedef int (*qsort_cmp)(const void *,const void *);
/*  mf_qsort2.cc*/
typedef int (*qsort2_cmp)(const void *, const void *, const void *);

extern void string_ptr_sort(unsigned char *base,uint32_t items,size_t size);
extern void radixsort_for_str_ptr(unsigned char* base[], uint32_t number_of_elements,
                                  size_t size_of_element,unsigned char *buffer[]);

extern void my_qsort(void *base_ptr, size_t total_elems, size_t size,
                     qsort_cmp cmp);
extern void my_qsort2(void *base_ptr, size_t total_elems, size_t size,
                      qsort2_cmp cmp, void *cmp_argument);

extern qsort2_cmp get_ptr_compare(size_t);
void   db_store_ptr(unsigned char *buff, size_t pack_length,clpsar_off_t pos);
#define sort_dynamic(A,cmp) my_qsort((A)->buffer, (A)->elements, (A)->size_of_element, (cmp))
extern bool db_init(void);
extern void db_end(int infoflag);
/**/
#define DB_INIT(name);   { g_progname= name; db_init(); }
/* Max width of screen (for error messages) */
#define SC_MAXWIDTH 256
#define ERRMSGSIZE  (SC_MAXWIDTH)  /* Max length of a error message */
#define NRERRBUFFS  (2) /* Buffers for parameters */
#define MY_FILE_ERROR  ((size_t) -1)


extern char  errbuff[NRERRBUFFS][ERRMSGSIZE];

extern const char *g_progname;               /* program-name (printed in errors) */


/// myf declared in defininations.h
typedef void (*error_handler_func)(uint32_t my_err,const char *str,myf _Flags);
extern error_handler_func error_handler_hook;
extern uint32_t my_file_limit;

/* root_alloc flags */
#define KEEP_PREALLOC        1
/* move used to free list and reuse them */
#define MARK_BLOCKS_FREE     2

extern ha_checksum db_checksum(ha_checksum crc,
                               const unsigned char *mem,
                               size_t count);

/*  db_getsystime.cc*/
extern uint64_t db_getsystime(void);
extern uint64_t db_micro_time(void);
extern uint64_t db_micro_time_and_time(time_t *time_arg);
time_t db_time_possible_from_micro  (uint64_t microtime);


/* character sets */
void *cs_alloc(size_t size);

extern uint32_t get_charset_number(const char *cs_name, uint32_t cs_flags);
extern uint32_t get_collation_number(const char *name);
extern const char *get_charset_name(uint32_t cs_number);

extern const CHARSET_INFO *get_charset(uint32_t cs_number);
extern const CHARSET_INFO *get_charset_by_name  (const char *cs_name);
extern const CHARSET_INFO *get_charset_by_csname(const char *cs_name,
                                                 uint32_t cs_flags);

extern bool resolve_charset(const char *cs_name,
                            const CHARSET_INFO *default_cs,
                            const CHARSET_INFO **cs);
extern bool resolve_collation(const char *cl_name,
                              const CHARSET_INFO *default_cl,
                              const CHARSET_INFO **cl);

extern void free_charsets(void);
extern char *get_charsets_dir(char *buf);

extern bool db_charset_same(const CHARSET_INFO *cs1, const CHARSET_INFO *cs2);

extern bool init_compiled_charsets(myf flags);
extern void add_compiled_collation(CHARSET_INFO *cs);

// db_error.cc
extern void my_error(int nr,myf _Flags, ...);

#define db_error  my_error

extern int  db_error_register(const char **errmsgs, int first, int last);
extern const char **error_unregister(int first, int last);
void error_unregister_all(void);
void my_printf_error(uint32_t error, const char *format, myf __Flags, ...);

#define db_printf_error   my_printf_error

void my_message(uint32_t error, const char *str, register myf __Flags);

#define db_message(A,B,C)   my_message(A,B,C)

#define MY_CHECK_ERROR  1   /* Params to my_end; Check open-close */
#define MY_GIVE_INFO    2   /* Give time info about process*/

/* statistics */
extern uint32_t    g_file_opened,g_stream_opened, g_tmp_file_created;
extern uint32_t    g_file_total_opened;
extern uint sys_usage_id;
extern bool g_init_done ;

/*   mulalloc.cc*/
void* util_multi_malloc(myf myFlags, ...) ;

extern int db_umask,  /* Default creation mask  */
           db_umask_dir;

extern uint64_t db_set_max_open_files(uint64_t files);
extern void db_free_open_file_info(void);
extern void free_defaults(char **argv);
extern void change_double_for_sort(double nr,unsigned char *to);

extern bool is_charset_same(const CHARSET_INFO *cs1, const CHARSET_INFO *cs2);

extern uint32_t   default_record_cache_size;
/**
  Swap the contents of two variables.
 */
#define swap_variables(TYPE, a, b) \
  do {                             \
    TYPE dummy;                    \
    dummy= a;                      \
    a= b;                          \
    b= dummy;                      \
  } while (0)

#define CMP_NUM(a,b)  (((a) < (b)) ? -1 : ((a) == (b)) ? 0 : 1)
#define FCMP(A,B) ((int) (A) - (int) (B))

#define portable_sizeof_char_ptr 8
#ifdef __cplusplus
}
#endif

#endif /* __DB_GLOBAL_H__*/
